﻿using System;
using System.Threading.Tasks;

namespace MaterialTypeRecognition.Shell.Utils.Devices
{
    public class SiemensSmart200
    {
        private HslCommunication.Profinet.Siemens.SiemensS7Net? _s7Net;

        /// <summary>
        /// 连接 PLC 设备
        /// </summary>
        /// <param name="ipAddress">PLC IP 地址</param>
        /// <param name="port">PLC 端口</param>
        /// <exception cref="InvalidOperationException">操作失败异常</exception>
        public async Task ConnectAsync(string ipAddress, int port = 102)
        {
            _s7Net = new HslCommunication.Profinet.Siemens.SiemensS7Net(HslCommunication.Profinet.Siemens.SiemensPLCS.S200Smart, ipAddress);
            _s7Net.Port = port;

            // 这里不适用 ConnectServerAsync，否则快速调用会 UI 线程死锁，这是 HSL 的问题。
            var result = await Task.Run(() => _s7Net.ConnectServer()).ConfigureAwait(false);

            if (!result.IsSuccess)
            {
                _s7Net = null; // 释放对象
                throw new InvalidOperationException($"连接 PLC 失败，错误码 {result.ErrorCode}.");
            }
        }

        /// <summary>
        /// 关闭 PLC 连接
        /// </summary>
        public async Task CloseAsync()
        {
            if (_s7Net != null)
            {
                // 我还是不想调用异步方法，因为 HSL 异步封装存在问题。
                await Task.Run(() => _s7Net.ConnectClose()).ConfigureAwait(false);
                _s7Net = null; // 释放对象
            }
        }

        /// <summary>
        /// 写入一个 bool 数据到 PLC 设备
        /// </summary>
        /// <param name="address">PLC地址</param>
        /// <param name="value">数据值</param>
        /// <exception cref="InvalidOperationException">操作失败异常</exception>
        public async Task WriteBoolAsync(string address, bool value)
        {
            if (_s7Net == null)
            {
                throw new InvalidOperationException("设备未连接！");
            }

            var result = await _s7Net.WriteAsync(address, value).ConfigureAwait(false);

            if (!result.IsSuccess)
            {
                throw new InvalidOperationException($"写入数据失败，错误码 {result.ErrorCode}.");
            }
        }
    }
}
